(function($){
    /**
     * 默认配置. 
     */
    var _defaultConfig = {
        queryDelay : 500,
        isAlwaysShow : false,   //默认点击搜索结果列表项时隐藏.
        listHeight : 200    //搜索结果列表默认200px.
    };    
    /**
     * 键盘输入事件.    
     * @event keyup 
     * @param {String} TextBox value
     */
    var EVT_Keyup = 'keyup';
    /**
     * 搜索结果列表项点击事件.
     * @event select
     */
    var EVT_Select = 'select';    
    /**
     * 自动完成框.
     * @class AutoCompleteBox
     * @constructor 
     * @param {Selector} $wrapper
     * @param {Object} config
     */
    function _AutoCompleteBox($wrapper, config){
        var _this = this;
        
        this.queryTaskPtr = null;
        
        Observable.enable(_this);
        _this.config = $.extend({}, _defaultConfig, config);
        this.$wrapper = $($wrapper).addClass('autoCompleteBoxWrapper');
        this.$wrapper.data('autoCompleteBox', this);
        
        if(this.config['theme']){
            this.$wrapper.addClass(this.config['theme']);
        }
        
        this.$wrapper.style(this.config['style']);
        
        this.$inputBox = $('<input class="autoCompleteBox"/>').appendTo(this.$wrapper);
        
        if(this.config['placeholder']){
            this.$inputBox.attr('placeholder', this.config['placeholder']);
        }
        
        if(this.config['events']){
            this.on(this.config['events']);
        }
        
        this.$list = $('<div class="autoCompleteListOptions"></div>').appendTo(this.$wrapper);
        (function(){
            _this.$list.css({
                //TODO:有时_this.$inputBox是隐藏的， 计算的height为0, bug!
                top : Math.max(_this.$inputBox.height() + 2, 27)
            });    
        }).defer(0);
        
        if(_this.config['closable']){
            _this.$cancelButton = $('<button class="cancelSearchBtn"></button');
            _this.$cancelButton.appendTo(this.$wrapper);
            _this.$cancelButton.click(function(){
                _this.listView.hide();
                _this.$inputBox.val('');
                _this.value = '';
            });
        }
         
        this.listView = this.$list.listView({
            itemTmp : _this.config['itemTmp'],
            closable : false,
            key : _this.config['key'], 
            height : _this.config['listHeight']
        }).data('listView');
        
        this.listView.on('itemClick', function($listViewItem){
            _this.fire(EVT_Select, $listViewItem);
            if(_this.config['isAlwaysShow'] !== true){
                _this.listView.hide();
                _this.$inputBox.val('');
                _this.value = '';
            }
        });
        
        $(document.body).click(function(e){
            if(!_this.$wrapper.contains(e.target)){
                if(_this.config['isAlwaysShow'] !== true){
                    _this.listView.hide();
                    _this.$inputBox.val('');
                    _this.value = '';
                }
            }
        });
        
        this.$inputBox.on({
            focus : function(e){
                if(_this.listView.hasItem()){
                    _this.listView.show();
                }
            }
        });
        
        this.$inputBox.on({
            keyup : function(e){
                var value = _this.getValue();
                if(!value || _this.value == value){
                    if(e.keyCode == 37 || e.keyCode == 38){
                        _this.listView.backSelect();
                    } else if(e.keyCode == 39 || e.keyCode == 40){
                        _this.listView.forwardSelect();                        
                    } else if(e.keyCode == 13){
                        _this.listView.selectCurrentItem();
                    }
                    return;                
                } else{
                    _this.value = value; 
                       
                    if(_this.queryTaskPtr){
                        window.clearTimeout(_this.queryTaskPtr);
                    }
                    _this.queryTaskPtr = (function(){
                        _this.listView.show().showMask();
                        
                        $.get(_this.getApi())
                        .done(ujs.hr(function(data){
                            _this.listView.load(data['users']);
                            _this.queryTaskPtr = null;                        
                        }))
                        .fail(function(){
                            _this.listView.load([]);
                        })
                        .always(function(){
                            _this.listView.hideMask();
                        });
                         
                    }).defer(_this.config['queryDelay']);
                }
            }
        });        
    }
    
    /**
     * 获取自动完成框的值.
     * @method getValue
     * @return {String} 自动完成框的值.
     */
    _AutoCompleteBox.prototype.getValue = function(){
        return this.$inputBox.val().trim();
    };
    
    /**
     * 获取Api接口.
     * @method getApi
     * @return {String|Function} : 接口地址或函数. 
     */
    _AutoCompleteBox.prototype.getApi = function(){
        var configApi = this.config['api'];
        if(Type.isFunction(configApi)){
            configApi = configApi.call(this);
        } 
        if(Type.isString(configApi)){
            return configApi.format({
                text : window.encodeURIComponent(this.getValue())
            });
        } else {
            return null;
        }
    };

    /**
     * 设置Api接口. 
     * @method setApi
     * @param {String|Function} api 字符串查询提交地址或函数.
     */
    _AutoCompleteBox.prototype.setApi = function(api){
        this.config['api'] = api;
        return this;
    };
    
    //------------------------------------------------------------------
    
    //init interface.
    $.fn.autoCompleteBox = function(config){        
        this.each(function(){
            new _AutoCompleteBox(this, config);
        });
        return this;
    };    
})($);